package org.mspring.mlog.security;

import org.mspring.mlog.cache.UserCacheService;
import org.mspring.mlog.entity.NodeEntity;
import org.mspring.mlog.entity.ResourceEntity;
import org.mspring.mlog.entity.RoleEntity;
import org.mspring.mlog.entity.UserEntity;
import org.mspring.mlog.service.NodeEntityService;
import org.mspring.mlog.service.ResourceEntityService;
import org.mspring.mlog.service.RoleEntityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @author Gao Youbo
 * @since 2014-09-10 17:47:11
 */
@Component
public class DefaultUserDetailsService implements UserDetailsService {

    private RoleEntityService roleEntityService;
    private NodeEntityService nodeEntityService;
    private UserCacheService userCacheService;
    private ResourceEntityService resourceEntityService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity user = userCacheService.getByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        }
        Collection<GrantedAuthority> grantedAuths = obtionGrantedAuthorities(user);

        boolean enable = !user.getDeleted();
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
                user.getUsername(),
                user.getPassword(),
                enable,
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                grantedAuths
        );
    }

    /**
     * 取得用户的权限
     *
     * @param user
     * @return
     */
    private Set<GrantedAuthority> obtionGrantedAuthorities(UserEntity user) {
        Set<GrantedAuthority> authSet = new HashSet<>();

        // 获取用户所有的角色
        List<RoleEntity> roles = roleEntityService.listByUser(user.getId());

        for (RoleEntity role : roles) {
            // 获取角色所拥有的资源
            List<ResourceEntity> resources = resourceEntityService.listByRole(role.getId());
            for (ResourceEntity res : resources) {
                authSet.add(new SimpleGrantedAuthority("resource_" + res.getId()));
            }

            List<NodeEntity> nodes = nodeEntityService.listByRole(role.getId());
            Iterator<NodeEntity> it = nodes.iterator();
            while (it.hasNext()) {
                NodeEntity node = it.next();
                if (org.apache.commons.lang3.StringUtils.isNotBlank(node.getUrl())) {
                    authSet.add(new SimpleGrantedAuthority("node_" + node.getId()));
                }
            }
        }
        return authSet;
    }

    @Autowired
    public void setRoleEntityService(RoleEntityService roleEntityService) {
        this.roleEntityService = roleEntityService;
    }

    @Autowired
    public void setNodeEntityService(NodeEntityService nodeEntityService) {
        this.nodeEntityService = nodeEntityService;
    }

    @Autowired
    public void setUserCacheService(UserCacheService userCacheService) {
        this.userCacheService = userCacheService;
    }

    @Autowired
    public void setResourceEntityService(ResourceEntityService resourceEntityService) {
        this.resourceEntityService = resourceEntityService;
    }
}
